package com.syyo.gulimall.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.syyo.gulimall.admin.common.enums.ResultEnum;
import com.syyo.gulimall.admin.common.exception.SysException;
import com.syyo.gulimall.admin.domain.entity.SysMenu;
import com.syyo.gulimall.admin.domain.entity.SysRole;
import com.syyo.gulimall.admin.domain.req.RoleReq;
import com.syyo.gulimall.admin.domain.resp.RoleResp;
import com.syyo.gulimall.admin.mapper.SysRoleDeptMapper;
import com.syyo.gulimall.admin.mapper.SysRoleMapper;
import com.syyo.gulimall.admin.mapper.SysRoleMenuMapper;
import com.syyo.gulimall.admin.service.SysRoleService;
import com.syyo.gulimall.admin.utils.MyListUtils;
import com.syyo.gulimall.admin.utils.MyStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wang
 * @since 2020-07-17
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService {

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysRoleMenuMapper roleMenuMapper;

    @Autowired
    private SysRoleDeptMapper roleDeptMapper;

    @Override
    @Transactional
    public int add(RoleReq req) {
        SysRole sysRole = new SysRole();
        sysRole.setRoleName(req.getRoleName());
        sysRole.setRoleKey(req.getRoleKey());
        sysRole.setRemark(req.getRemark());
        LocalDateTime now = LocalDateTime.now();
        sysRole.setUpdateTime(now);
        sysRole.setCreateTime(now);
        int insert = roleMapper.insert(sysRole);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80011.getCode(), ResultEnum.E_80011.getMessage());
        }

        List<Integer> deptList = req.getDeptList();
        if (req.getDataScope() == 2 && MyListUtils.isNotEmpty(deptList)) {
            roleDeptMapper.addAll(sysRole.getRoleId(), deptList);
        }
        return insert;

    }

    @Override
    @Transactional
    public int del(Integer id) {
        // admin角色不能删除
        if (id == 1) {
            throw new SysException(ResultEnum.E_90007.getCode(), ResultEnum.E_90007.getMessage());
        }
        int insert = roleMapper.deleteById(id);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80012.getCode(), ResultEnum.E_80012.getMessage());
        }
        return insert;
    }

    @Override
    @Transactional
    public int edit(RoleReq req) {
        Integer roleId = req.getRoleId();
        SysRole sysRole = new SysRole();
        sysRole.setRoleId(req.getRoleId());
        sysRole.setRoleName(req.getRoleName());
        sysRole.setDataScope(req.getDataScope());
        sysRole.setRemark(req.getRemark());
        LocalDateTime now = LocalDateTime.now();
        sysRole.setUpdateTime(now);
        int insert = roleMapper.updateById(sysRole);
        if (insert != 1) {
            throw new SysException(ResultEnum.E_80013.getCode(), ResultEnum.E_80013.getMessage());
        }

        // 选择数据范围前，先删除角色关联的部门
        roleDeptMapper.del(roleId);
        List<Integer> deptList = req.getDeptList();
        if (req.getDataScope() == 2 && MyListUtils.isNotEmpty(deptList)) {
            // 添加新的角色关联部门
            Integer count = roleDeptMapper.addAll(roleId, deptList);
            if (count != deptList.size()) {
                throw new SysException(ResultEnum.E_80013.getCode(), ResultEnum.E_80013.getMessage());
            }
        }
        return insert;
    }

    @Override
    public RoleResp findOne(Integer id) {
        SysRole sysRole = roleMapper.selectById(id);

        // 查询对应的菜单
        List<Integer> list = roleMenuMapper.getMenuId(id);
        RoleResp roleResp = new RoleResp();
        roleResp.setRoleId(sysRole.getRoleId());
        roleResp.setRoleName(sysRole.getRoleName());
        roleResp.setRoleKey(sysRole.getRoleKey());
        roleResp.setDataScope(sysRole.getDataScope());
        roleResp.setRemark(sysRole.getRemark());
        roleResp.setCreateTime(sysRole.getCreateTime());
        roleResp.setMenuIdList(list);
        if (sysRole.getDataScope() == 2) {
            List<Integer> deptIdList = roleDeptMapper.getDeptById(id);
            roleResp.setDeptIdList(deptIdList);
        }
        return roleResp;
    }

    @Override
    public IPage<SysRole> findAll(Integer pageNum, Integer pageSize, RoleReq req) {
        Page<SysRole> teacherPage = new Page<SysRole>(pageNum, pageSize);
        QueryWrapper<SysRole> wrapper = new QueryWrapper<>();
        String roleName = req.getRoleName();
        //判断条件值是否为空，如果不为空拼接条件
        if (MyStringUtils.isNotEmpty(roleName)) {
            //构建条件
            wrapper.like("role_name", roleName);
        }
        return roleMapper.selectPage(teacherPage, wrapper);
    }

    @Override
    public Collection<GrantedAuthority> findByUsersId(Integer userId) {
        Set<SysRole> roles = roleMapper.findByUsersId(userId);

        //添加角色标识
        Set<String> permissions = roles.stream().filter(role -> MyStringUtils.isNotEmpty(role.getRoleKey())).map(SysRole::getRoleKey).collect(Collectors.toSet());
        //添加菜单的权限标识
        permissions.addAll(
                roles.stream().flatMap(role -> role.getMenus().stream())
                        .filter(menu -> MyStringUtils.isNotEmpty(menu.getPerms()))
                        .map(SysMenu::getPerms).collect(Collectors.toSet())
        );
        return permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public int auth(RoleReq req) {
        //校验角色id是否存在
        Integer roleId = req.getRoleId();
        SysRole sysRole = roleMapper.selectById(roleId);
        if (sysRole == null) {
            throw new SysException(ResultEnum.E_80015.getCode(), ResultEnum.E_80015.getMessage());
        }
        //添加角色菜单中间表
        List<Integer> menuIdList = req.getMenuIdList();
        if (MyListUtils.isNotEmpty(menuIdList)) {
            //删除该角色在中间表的权限信息
            roleMenuMapper.del(roleId);

            Integer add = roleMenuMapper.addAll(roleId, menuIdList);
            if (add != menuIdList.size()) {
                throw new SysException(ResultEnum.E_80011.getCode(), ResultEnum.E_80011.getMessage());
            }
        }
        return menuIdList.size();


    }
}
